package com.againstsky;

import java.io.Serializable;
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 * Created by agasinst on 2017/9/13.
 */
public class ABag<E> extends AbstractList<E> implements List<E>,Serializable{

    private static final Object[] EMPTY_ELEMENTDATA={};

    private static final Object[] DEFAULT_EMPTY_ELEMENTDATA={};
    
    private static final int DEFAULT_CAPACITY=10;//默认的数组长度

    private int size;//The size of the ArrayList (the number of elements it contains).

    transient Object[] elements;
    
    


    public ABag(){
        elements=DEFAULT_EMPTY_ELEMENTDATA;
    }

    public ABag(int initialCapacity){
        if(initialCapacity>0){
            elements=new Object[initialCapacity];

        }else if (initialCapacity==0){
            elements=EMPTY_ELEMENTDATA;
        }else {
            throw new IllegalArgumentException("initialCapacity必须大于或者等于0,你的参数:"+initialCapacity);
        }
    }

    public ABag(Collection<? extends E> c){
        elements=c.toArray();
        if((size=elements.length)!=0){
            if(elements.getClass()!=Object[].class){
                elements= Arrays.copyOf(elements,size,Object[].class);
            }
        }else {
            elements=EMPTY_ELEMENTDATA;
        }
    }

    //在内存稀缺的时候把elements的长度减少到内部元素的长度
    public boolean trimToSize(){
        if(size<elements.length){
            elements=(size==0)?EMPTY_ELEMENTDATA:Arrays.copyOf(elements,size);
            return true;
        }else {
            return false;
        }
    }

    @Override
    public E get(int index) {
        rangeCheck(index);
        return elementData(index);
    }

    @Override
    public boolean contains(Object o) {
        return indexOf(o)>=0;
    }

    @Override
    public int lastIndexOf(Object o) {
        if(o==null){
            for (int i=size-1;i>=0;i--)
                if(elements[i]==null)
                    return i;
        }else {
            for (int i=size-1;i>=0;i--)
                if(elements[i].equals(o))
                    return i;
        }
        return -1;
    }

    @Override
    public int indexOf(Object o) {
        if(o==null){
            for (int i = 0; i < size; i++)
                if(elements[i]==null)
                    return i;
        }else {
            for (int i = 0; i < size; i++)
                if(elements[i].equals(o))
                    return i;
        }
        return -1;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public boolean isEmpty() {
        return size==0;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        ABag<?> v= (ABag<?>) super.clone();
        v.elements=Arrays.copyOf(elements,size);
        return v;
    }

    @Override
    public Object[] toArray() {
        return Arrays.copyOf(elements,size);
    }
    
    private E elementData(int index){
        return (E) elements[index];
    }

    private void rangeCheck(int indxe){
        if (indxe>=size)
            throw new IndexOutOfBoundsException("下标越界 size:"+size+" indxe:"+indxe);
    }

    @Override
    public boolean add(E e) {
        ensureCapacityInternal(size+1);
        elements[size++]=e;
        return true;
    }


    //当数组中的元素个数等于
    private void ensureCapacityInternal(int minCapacity){
        if(elements==DEFAULT_EMPTY_ELEMENTDATA){
            minCapacity=Math.max(DEFAULT_CAPACITY,minCapacity);
        }
        ensureExplicitCapacity(minCapacity);
    }

    private void ensureExplicitCapacity(int minCapacity) {
        if(minCapacity>elements.length){
            grow(minCapacity);
        }
    }
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 16;


    private void grow(int minCapacity) {
        int oldC=elements.length;
        int newC=oldC+(oldC>>1);
        if(newC<minCapacity) newC=minCapacity;
        if(newC>MAX_ARRAY_SIZE) {
            newC = hugeCapacity(minCapacity);
        }

        elements=Arrays.copyOf(elements,newC);
    }

    private int hugeCapacity(int minC){
        if(minC<0){
            throw new OutOfMemoryError();
        }
        return minC>MAX_ARRAY_SIZE?Integer.MAX_VALUE:MAX_ARRAY_SIZE;
    }
}
